package com.lagou.SqlSessionFactory;

import com.lagou.pojo.Configuration;
import com.lagou.pojo.MappedStatement;

import java.lang.reflect.*;
import java.sql.CallableStatement;
import java.util.List;
import java.util.Objects;

/**
 * <pre>
 * 描述：TODO
 * </pre>
 *
 * @类名：com.lagou.SqlSessionFactory.DefaultSqlSession
 * @作者 mengwei
 * 创建日期：2020/9/28 10:37
 */
public class DefaultSqlSession implements SqlSession {
    private Configuration configuration;

    public DefaultSqlSession(Configuration configuration) {
        this.configuration = configuration;
    }

    @Override
    public <T> T selectOne(String mapperId, Object ...params) throws Exception {
        List<Object> list = selectList(mapperId, params);
        if (list.size() ==1) return (T) list.get(0);
        throw new RuntimeException("selectOne查询到多条结果或结果为空："+list.size());
    }

    @Override
    public <T> List<T> selectList(String mapperId,Object ...params) throws Exception {
        Executer executer = new SimpleExecuter();
        MappedStatement mappedStatement = configuration.getMappedStatementMap().get(mapperId);
        List<T> list = executer.query(configuration,mappedStatement,params);
        return list;
    }

    @Override
    public int modify(String mapperId,Object ...params) throws Exception {
        Executer executer = new SimpleExecuter();
        MappedStatement mappedStatement = configuration.getMappedStatementMap().get(mapperId);
        return executer.modify(configuration,mappedStatement,params);
    }



    @Override
    public <T> T getMapper(Class<?> clazz) {
        Object proxyInstance = Proxy.newProxyInstance(DefaultSqlSession.class.getClassLoader(), new Class[]{clazz}, new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//                proxy 当前代理对象的引用
//                method 当前被调用方法的引用
//                args  当前被调用方法传递的参数
                String methodName = method.getName();
                String className = method.getDeclaringClass().getName();
                String mapperId =  className + "." +methodName;

                String qualifiedName = configuration.getMappedStatementMap().get(mapperId).getQualifiedName();
                switch (qualifiedName){
                    case "select":{
                        //                获取定义的返回类型
                        Type genericReturnType = method.getGenericReturnType();
//                判断是否进行  泛型类型参数化
                        if (genericReturnType instanceof ParameterizedType){
                            return selectList(mapperId,args);
                        }

                        return selectOne(mapperId,args);
                    }
                    case "delete":
                    case "update":
                    case "insert":{
                        return modify(mapperId,args);
                    }
                    default: return null;
                }

            }
        });
        return (T) proxyInstance;
    }



//    @Override
//    public <T> T getMapper(Class<?> clazz) {
//        Object proxyInstance = Proxy.newProxyInstance(DefaultSqlSession.class.getClassLoader(), new Class[]{clazz}, new InvocationHandler() {
//            @Override
//            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
////                proxy 当前代理对象的引用
////                method 当前被调用方法的引用
////                args  当前被调用方法传递的参数
//                String methodName = method.getName();
//                String className = method.getDeclaringClass().getName();
//                String mapperId =  className + "." +methodName;
//
//
////                to
////                获取定义的返回类型
//                Type genericReturnType = method.getGenericReturnType();
////                判断是否进行  泛型类型参数化
//                if (genericReturnType instanceof ParameterizedType){
//                    return selectList(mapperId,args);
//                }
//
//                return selectOne(mapperId,args);
//            }
//        });
//        return (T) proxyInstance;
//    }
}
